home *** CD-ROM | disk | FTP | other *** search
- /*
- * (c)Copyright 1992-1997 Obvious Implementations Corp. Redistribution and
- * use is allowed under the terms of the DICE-LICENSE FILE,
- * DICE-LICENSE.TXT.
- */
-
- /*
- * CODE.C
- */
-
- #include "defs.h"
-
- #define DISOBJ_C
-
- #ifdef AMIGA
- #include "/das/ops.c"
- #else
- #include "../das/ops.c"
- #endif
-
- OpCod *BaseCod;
-
- Prototype void InitCodeList(void);
- Prototype void DumpCode(FILE *fi, short srcHunk, long begOffset, long endOffset);
- Prototype RelocInfo *RelocAtOffset(long offset, short hunkNo);
- Prototype OpCod *DecodeOpCode(uword opCode, short *pmode1, short *pmode2, short *psiz, short *prs, short *prd);
- Prototype int MatchEa(uword opCode, short ea, short reg, long modes);
- Prototype int MatchSiz(uword opCode, OpCod *oc);
- Prototype int ExtensionWords(OpCod *oc, short mode, short opsize, uword *oper, FILE *fi);
- Prototype int IndexFormatExtWords(uword ext);
- Prototype char *ModeToStr(long offset, short srcHunk, uword opCode, uword **pwp, short mode, int altMode, short siz, short reg, short special);
-
- /*
- * Reduce search requirements by splitting opcodes into a set of 16
- * lists based on their msb 4 bits (which never have dynamic info in them)
- */
-
- void
- InitCodeList(void)
- {
- OpCod *oc;
-
- for (oc = Codes; oc->OpName; ++oc) {
- if (oc->Id < 0)
- continue;
- oc->SibNext = BaseCod;
- BaseCod = oc;
- }
- }
-
- void
- DumpCode(FILE *fi, short srcHunk, long begOffset, long endOffset)
- {
- RelocInfo *r;
-
- while (begOffset < endOffset) {
- uword opCode;
- static uword oper[32];
- short words1;
- short words2;
- short i;
- short col;
- OpCod *oc;
- short mode1;
- short mode2;
- short siz;
- short rs;
- short rd;
-
- col = cprintf(" %02x.%08lx ", srcHunk, begOffset + StartPc);
-
- if ((r = RelocAtOffset(begOffset, srcHunk)) != NULL) {
- long data = LoadRelocData(fi, r);
- col += cprintf(" %s\n", RelocToStr(r, data, 1, 0, -1));
- begOffset += r->ri_RelocSize;
- continue;
- }
- if (freadl(&opCode, 2, 1, fi) != 1)
- cerror(EFATAL, "Unexpected EOF");
- begOffset += 2;
-
- col += cprintf(" %04x", opCode);
-
- oc = DecodeOpCode(opCode, &mode1, &mode2, &siz, &rs, &rd);
- if (oc) {
- words1 = ExtensionWords(oc, mode1, siz, oper, fi);
- words2 = ExtensionWords(oc, mode2, siz, oper + words1, fi);
- } else {
- words1 = 0;
- words2 = 0;
- }
-
- for (i = 0; i < words1 + words2; ++i) {
- r = RelocAtOffset(begOffset + i * 2, srcHunk);
- if (r) {
- char *str;
-
- switch(r->ri_RelocSize) {
- case 1:
- str = RelocToStr(r, oper[i] >> 8, 1, 1, -1);
- break;
- case 2:
- str = RelocToStr(r, oper[i], 1, 2, -1);
- break;
- case 4:
- str = RelocToStr(r, (oper[i] << 16) | oper[i+1], 1, 4, -1);
- ++i;
- break;
- default:
- str = RelocToStr(r, 0, 1, 0, -1);
- break;
- }
- col += cprintf(" %s", str);
- } else {
- if ((r = RelocAtOffset(begOffset + i * 2 + 1, -1)) != NULL) {
- if (r->ri_RelocSize != 1)
- cerror(EWARN, "Expected 8 bit reloc");
- col += cprintf(" %s", RelocToStr(r, oper[i] & 0xFF, 1, 2, -1));
- } else {
- col += cprintf(" %04x", oper[i]);
- }
- }
- }
-
- ++col;
- putc(' ', stdout);
- while (col < 40) {
- ++col;
- putc(' ', stdout);
- }
-
- /*
- * decode effective addresses
- */
-
- if (oc) {
- col += cprintf("%s", oc->OpName);
-
- col += 3;
-
- switch(siz) {
- case 0:
- printf(" ");
- break;
- case 1:
- printf(".B ");
- break;
- case 2:
- printf(".W ");
- break;
- case 4:
- printf(".L ");
- break;
- default:
- printf(".? ");
- break;
- }
- while (col < 48) {
- putc(' ', stdout);
- ++col;
- }
- {
- uword *iptr = oper; /* ptr to beginning of extension */
-
- if (mode2 == AB_REGS)
- ++iptr;
- if (mode1)
- printf("%s", ModeToStr((iptr - oper) * 2 + begOffset, srcHunk, opCode, &iptr, mode1, mode2, siz, rs, oc->Special));
- if (mode1 && mode2)
- printf(",");
- if (mode2) {
- if (mode2 == AB_REGS)
- iptr = oper;
- printf("%s", ModeToStr((iptr - oper) * 2 + begOffset + words1, srcHunk, opCode, &iptr, mode2, mode1, siz, rd, oc->Special));
- }
- }
- }
- puts("");
- begOffset += (words1 + words2) * 2;
- }
- if (begOffset > endOffset)
- fseek(fi, endOffset - begOffset, SEEK_CUR);
- }
-
- RelocInfo *
- RelocAtOffset(long offset, short hunkNo)
- {
- RelocInfo *r = FindRelocOffset(offset, hunkNo);
-
- if (r && r->ri_SrcOffset == offset)
- return(r);
- return(NULL);
- }
-
- /*
- * returns # of extension words and fills up ea structures
- * accordingly.
- */
-
- OpCod *
- DecodeOpCode(uword opCode, short *pmode1, short *pmode2, short *psiz, short *prs, short *prd)
- {
- OpCod *oc;
-
- *pmode1 = 0;
- *pmode2 = 0;
- *psiz = 0;
-
- /*
- * find op-code
- */
-
- for (oc = BaseCod; oc; oc = oc->SibNext) {
- short am;
-
- {
- uword template;
-
- if ((opCode & oc->Template) != oc->Template)
- continue;
-
- if ((oc->SModes & AF_BBRANCH) && (char)opCode == 0)
- continue;
- if ((oc->SModes & AF_WBRANCH) && (char)opCode)
- continue;
-
- template = opCode;
-
- if (oc->SModes & (AF_BBRANCH|AF_WBRANCH))
- template &= 0xFF00;
-
- switch(oc->Special) {
- case 0:
- case IMM07: /* unused */
- break;
- case IMM18:
- template &= 0xF1FF;
- break;
- case IMM0F:
- template &= 0xFFF0;
- break;
- case IMM256:
- template &= 0xFF00;
- break;
- case IMMBR: /* unused */
- case IMMB:
- break;
- default:
- cerror(ESOFT, "Unknown special code %s/%d", oc->OpName, oc->Special);
- }
-
- if (oc->B_EAs >= 0)
- template &= ~(7 << oc->B_EAs);
- if (oc->B_Rs >= 0)
- template &= ~(7 << oc->B_Rs);
- if (oc->B_EAd >= 0)
- template &= ~(7 << oc->B_EAd);
- if (oc->B_Rd >= 0)
- template &= ~(7 << oc->B_Rd);
- if (oc->B_Siz >= 0)
- template &= ~(3 << oc->B_Siz);
-
- if (template != oc->Template) {
- if (DDebug)
- printf("Template mismatch %04x %04x (%d %d %d %d %d)\n",
- template, oc->Template, oc->B_EAs, oc->B_Rs, oc->B_EAd, oc->B_Rd, oc->B_Siz
- );
- continue;
- }
- }
- if (DDebug)
- printf("template match %s\n", oc->OpName);
-
- am = MatchEa(opCode, oc->B_EAs, oc->B_Rs, oc->SModes);
- if (DDebug)
- printf("r = %d\n", am);
- if (am < 0)
- continue;
- if (oc->B_Rs >= 0)
- *prs = (opCode >> oc->B_Rs) & 7;
- *pmode1 = am;
-
- am = MatchEa(opCode, oc->B_EAd, oc->B_Rd, oc->DModes);
- if (DDebug)
- printf("r = %d\n", am);
- if (am < 0)
- continue;
- if (oc->B_Rd >= 0)
- *prd = (opCode >> oc->B_Rd) & 7;
- *pmode2 = am;
-
- am = MatchSiz(opCode, oc);
- if (am < 0)
- continue;
- *psiz = am;
- break;
- }
- return(oc);
- }
-
- int
- MatchEa(uword opCode, short ea, short reg, long modes)
- {
- short i = 0;
-
- if (DDebug)
- printf("matchea %04x %d %d %08lx\n", opCode, ea, reg, modes);
- if (ea >= 0) {
- if (reg >= 0) {
- reg = (opCode >> reg) & 7;
- } else {
- reg = 0;
- }
- ea = (opCode >> ea) & 7;
- switch(ea) {
- case 0:
- i = AB_DN;
- break;
- case 1:
- i = AB_AN;
- break;
- case 2:
- i = AB_INDAN;
- break;
- case 3:
- i = AB_INDPP;
- break;
- case 4:
- i = AB_MMIND;
- break;
- case 5:
- i = AB_OFFAN;
- break;
- case 6:
- i = AB_OFFIDX;
- break;
- case 7:
- switch(reg) {
- case 0:
- i = AB_ABSW;
- break;
- case 1:
- i = AB_ABSL;
- break;
- case 2:
- i = AB_OFFPC;
- break;
- case 3:
- i = AB_OFFIDXPC;
- break;
- case 4:
- i = AB_IMM;
- break;
- default:
- return(-1);
- }
- }
- if ((modes & (1 << i)) == 0)
- i = -1;
- } else if (modes) {
- for (i = 0; i < 32; ++i) {
- if (modes - (1 << i) == 0)
- break;
- }
- }
- return(i);
- }
-
- int
- MatchSiz(uword opCode, OpCod *oc)
- {
- short siz = oc->B_Siz;
- short sizes = oc->Sizes;
-
- if (siz >= 0) {
- switch((opCode >> siz) & 3) {
- case 0:
- sizes &= S_B;
- break;
- case 1:
- sizes &= S_W;
- break;
- case 2:
- sizes &= S_L;
- break;
- case 3:
- return(-1);
- }
- }
- switch(sizes) {
- case S_B:
- return(1);
- case S_W:
- return(2);
- case S_L:
- return(4);
- }
- if (sizes == 0)
- return(0);
- cerror(EFATAL, "Software error, opcode/siz %04x %d %04x\n", opCode, siz, sizes);
- return(-1);
- }
-
- int
- ExtensionWords(OpCod *oc, short mode, short opsize, uword *oper, FILE *fi)
- {
- short i = ExtWords[mode];
-
- if (i == -1) { /* imm/branch */
- if (oc->Special == IMMB)
- i = 1;
- else if (oc->Special || (oc->SModes & AF_BBRANCH))
- i = 0;
- else
- i = (opsize + 1) >> 1; /* 1 for bw, 2 for long */
- if (i)
- freadl(oper, 2, i, fi);
- } else if (i == -2) {
- freadl(oper, 2, 1, fi);
- i = IndexFormatExtWords(*oper);
- if (i > 1)
- freadl(oper + 1, 2, i - 1, fi);
- } else if (i) {
- freadl(oper, 2, i, fi);
- }
- return(i);
- }
-
- int
- IndexFormatExtWords(uword ext)
- {
- int n = 1;
-
- if (ext & 0x0100) {
- switch(ext & 0x0030) { /* base displacement */
- case 0x0000:
- case 0x0010:
- break;
- case 0x0020:
- ++n;
- break;
- case 0x0030:
- ++n;
- ++n;
- break;
- }
- switch(ext & 0x0003) { /* outder displacement */
- case 0x0000:
- case 0x0001:
- break;
- case 0x0002:
- ++n;
- break;
- case 0x0003:
- ++n;
- ++n;
- break;
- }
- }
- return(n);
- }
-
- /*
- * offset is the offset of the first extension word for this ea.
- */
-
- char *
- ModeToStr(long offset, short srcHunk, uword opCode, uword **pwp, short mode, int altMode, short siz, short reg, short special)
- {
- uword *wptr = *pwp;
- RelocInfo *r = NULL;
- static char Buf[SMAX_BUF+128];
-
-
- switch(mode) {
- case AB_DN:
- sprintf(Buf, "D%d", reg);
- break;
- case AB_AN:
- sprintf(Buf, "A%d", reg);
- break;
- case AB_INDAN:
- sprintf(Buf, "(A%d)", reg);
- break;
- case AB_INDPP:
- sprintf(Buf, "(A%d)+", reg);
- break;
- case AB_MMIND:
- sprintf(Buf, "-(A%d)", reg);
- break;
- case AB_OFFAN:
- r = RelocAtOffset(offset, srcHunk);
- sprintf(Buf, "%s(A%d)", RelocToStr(r, (short)wptr[0], 0, 2, -1), reg);
- ++wptr;
- break;
- case AB_OFFIDX:
- case AB_OFFIDXPC:
- {
- char regbuf[4]; /* base register */
- char idxbuf[8]; /* idx register */
- uword ext = *wptr;
-
- if (mode == AB_OFFIDX) {
- regbuf[0] = 'A';
- regbuf[1] = reg + '0';
- } else {
- regbuf[0] = 'p';
- regbuf[1] = 'c';
- }
- regbuf[2] = 0;
-
- {
- idxbuf[0] = (ext & 0x8000) ? 'A' : 'D';
- idxbuf[1] = ((ext >> 12) & 7) + '0';
- idxbuf[2] = '.';
- idxbuf[3] = (ext & 0x0800) ? 'L' : 'W';
- idxbuf[4] = 0;
-
- switch(ext & 0x0600) {
- case 0x0200:
- strcpy(idxbuf + 4, "*2");
- break;
- case 0x0400:
- strcpy(idxbuf + 4, "*4");
- break;
- case 0x0600:
- strcpy(idxbuf + 4, "*8");
- break;
- }
- }
- if (ext & 0x0100) { /* MC68020 full format */
- char *ptr = Buf;
- short hda = 0;
-
- ++wptr;
- offset += 2; /* skip first extension word */
-
- *ptr++ = '(';
- if (ext & 0x0007)
- *ptr++ = '[';
-
- switch(ext & 0x0030) {
- case 0x0000:
- ptr += csprintf(ptr, "<BADBD>");
- hda = 1;
- break;
- case 0x0010: /* null */
- break;
- case 0x0020: /* word */
- r = RelocAtOffset(offset, srcHunk);
- ptr += csprintf(ptr, "%s", RelocToStr(r, (short)*wptr, 0, 2, (mode == AB_OFFIDXPC) ? srcHunk : -1));
- ++wptr;
- offset += 2;
- hda = 1;
- break;
- case 0x0030: /* long */
- r = RelocAtOffset(offset, srcHunk);
- ptr += csprintf(ptr, "%s", RelocToStr(r, *(long *)wptr, 0, 4, (mode == AB_OFFIDXPC) ? srcHunk : -1));
- ++wptr;
- ++wptr;
- offset += 4;
- hda = 1;
- break;
- }
- if (hda) {
- *ptr++ = ',';
- hda = 0;
- }
- if ((ext & 0x0080) == 0) {
- ptr += csprintf(ptr, "%s", regbuf);
- hda = 1;
- }
- /*
- * if indirect post-indexed close bracket
- */
- if ((ext & 0x0044) == 0x0004) {
- *ptr++ = ']';
- hda = 1;
- }
- if (hda) {
- *ptr++ = ',';
- hda = 0;
- }
-
- /*
- * index reg
- */
-
- if ((ext & 0x0040) == 0) {
- ptr += csprintf(ptr, "%s", idxbuf);
- hda = 1;
- }
-
- if ((ext & 0x0044) != 0x0004) { /* not ind post indexed */
- if (ext & 0x0007) {
- *ptr++ = ']';
- hda = 1;
- }
- }
-
- /*
- * outer displacement
- */
-
- switch(ext & 0x0003) {
- case 0x0000:
- case 0x0001: /* null */
- break;
- case 0x0002: /* word */
- r = RelocAtOffset(offset, srcHunk);
- ptr += csprintf(ptr, "%s", RelocToStr(r, (short)*wptr, 0, 2, -1));
- ++wptr;
- hda = 1;
- break;
- case 0x0003: /* long */
- r = RelocAtOffset(offset, srcHunk);
- ptr += csprintf(ptr, "%s", RelocToStr(r, *(long *)wptr, 0, 4, -1));
- ++wptr;
- ++wptr;
- hda = 1;
- break;
- }
- *ptr++ = ')';
- *ptr = 0;
- } else { /* MC68000/020 brief */
- r = RelocAtOffset(offset, srcHunk);
- if (r == NULL)
- r = RelocAtOffset(offset + 1, srcHunk);
- sprintf(Buf, "%s(%s,%s)", RelocToStr(r, (char)ext, 0, 1, (mode == AB_OFFIDXPC) ? srcHunk : -1), regbuf, idxbuf);
- ++wptr;
- }
- }
- break;
- case AB_ABSW:
- r = RelocAtOffset(offset, srcHunk);
- sprintf(Buf, "%s.W", RelocToStr(r, wptr[0], 0, 2, srcHunk));
- ++wptr;
- break;
- case AB_ABSL:
- r = RelocAtOffset(offset, srcHunk);
- if (r == NULL)
- r = RelocAtOffset(offset + 2, srcHunk);
- sprintf(Buf, "%s", RelocToStr(r, (wptr[0] << 16) | wptr[1], 0, 4, srcHunk));
- wptr += 2;
- break;
- case AB_OFFPC:
- {
- long addoff;
-
- /*
- * Attempt to do the relocation. If we can get our hands on
- * a symbol we are in good shape.
- */
-
- r = RelocAtOffset(offset, srcHunk);
- addoff = FixRelocOffset(r, offset);
-
- sprintf(Buf, "%s(pc)", RelocToStr(r, (short)wptr[0] + addoff, 0, 0, srcHunk));
- }
- ++wptr;
- break;
- case AB_IMM:
- switch(special) {
- case IMM18:
- {
- short cnt = (opCode >> 9) & 7;
-
- if (cnt == 0)
- cnt = 8;
- sprintf(Buf, "#%d", cnt);
- }
- break;
- case IMM0F:
- sprintf(Buf, "#%d", opCode & 15); /* warning, decimal */
- break;
- case IMM256:
- r = RelocAtOffset(offset - 1, srcHunk);
- if (r == NULL)
- r = RelocAtOffset(offset - 2, srcHunk);
- sprintf(Buf, "#%s", RelocToStr(r, (char)opCode, 0, 1, -1));
- break;
- case IMMB: /* next byte */
- r = RelocAtOffset(offset, srcHunk);
- if (r == NULL)
- r = RelocAtOffset(offset + 1, srcHunk);
- sprintf(Buf, "#%s", RelocToStr(r, (char)wptr[0], 0, 1, -1));
- ++wptr;
- break;
- default:
- r = RelocAtOffset(offset, srcHunk);
- switch(siz) {
- case 0:
- sprintf(Buf, "#?");
- break;
- case 1:
- if (r == NULL)
- r = RelocAtOffset(offset + 1, srcHunk);
- sprintf(Buf, "#%s", RelocToStr(r, (short)wptr[0], 0, 1, -1));
- ++wptr;
- break;
- case 2:
- sprintf(Buf, "#%s", RelocToStr(r, (short)wptr[0], 0, 2, -1));
- ++wptr;
- break;
- case 4:
- sprintf(Buf, "#%s", RelocToStr(r, (wptr[0] << 16) | wptr[1], 0, 4, -1));
- wptr += 2;
- break;
- default:
- sprintf(Buf, "#?");
- break;
- }
- break;
- }
- break;
- case AB_REGS:
- {
- short i;
- short j = 0;
- short beg = -1;
-
- for (i = 0; i < 16; ++i) {
- short regNo;
-
- if (altMode == AB_MMIND)
- regNo = wptr[0] & (1 << (15 - i));
- else
- regNo = wptr[0] & (1 << i);
-
- if (regNo) {
- if (beg == -2)
- j += csprintf(Buf + j, "/");
- if (beg < 0) {
- if (i < 8)
- j += csprintf(Buf + j, "D%d", i);
- else
- j += csprintf(Buf + j, "A%d", i - 8);
- beg = i;
- }
- }
- if (regNo == 0 || i == 8) {
- if (beg >= 0) {
- --i;
- if (beg < i) {
- if (i < 8)
- j += csprintf(Buf + j, "-D%d", i);
- else
- j += csprintf(Buf + j, "-A%d", i - 8);
- }
- ++i;
- beg = -2;
- }
- }
- }
- }
- ++wptr;
- break;
- case AB_BBRANCH:
- case AB_WBRANCH:
- {
- long addoff;
-
- if (opCode & 0xFF) {
- r = RelocAtOffset(offset - 1, srcHunk);
- addoff = FixRelocOffset(r, offset);
-
- if (r == NULL) {
- r = RelocAtOffset(offset - 2, srcHunk);
- addoff = FixRelocOffset(r, offset);
- }
- sprintf(Buf, "%s", RelocToStr(r, (char)opCode + addoff, 0, 4, srcHunk));
- } else {
- r = RelocAtOffset(offset, srcHunk);
- addoff = FixRelocOffset(r, offset);
-
- sprintf(Buf, "%s", RelocToStr(r, (short)wptr[0] + addoff, 0, 4, srcHunk));
- /* XXX ? */
- ++wptr;
- }
- }
- break;
- case AB_CCR:
- sprintf(Buf, "CCR");
- break;
- case AB_SR:
- sprintf(Buf, "SR");
- break;
- case AB_USP:
- sprintf(Buf, "USP");
- break;
- default:
- return("?");
- }
- *pwp = wptr;
- return(Buf);
- }
-
-